#!/usr/bin/env bash

# imports
source "${KOGITO_HOME}"/launch/logging.sh
source "${KOGITO_HOME}"/launch/kogito-persistence.sh

S2I_DESTINATION_DIR="${S2I_DESTINATION_DIR:-/tmp}"
S2I_ARTIFACTS_DIR="${S2I_DESTINATION_DIR}/artifacts"
S2I_SOURCE_DIR="${S2I_DESTINATION_DIR}/src"
PROJECT_GROUP_ID="${PROJECT_GROUP_ID:-com.company}"
PROJECT_ARTIFACT_ID="${PROJECT_ARTIFACT_ID:-project}"
PROJECT_VERSION="${PROJECT_VERSION:-1.0-SNAPSHOT}"
artifactDir="target"
readonly QUARKUS_RUNTIME_TYPE="quarkus"
readonly SPRINGBOOT_RUNTIME_TYPE="springboot"

if [ ! -z "${ARTIFACT_DIR}" ]; then
    artifactDir="${ARTIFACT_DIR}"
fi

# setup file permissions for injected content
if [ -d "${S2I_ARTIFACTS_DIR}" ]; then
    chmod -R ug+rwX "${S2I_ARTIFACTS_DIR}"
fi


function manage_incremental_build() {
    if [ -d /tmp/artifacts ]; then
        log_info "Expanding artifacts from incremental build..."
        ( cd /tmp/artifacts && tar cf - . ) | ( cd ${HOME} && tar xvf - )
        rm -rf /tmp/artifacts
    fi
}


function assemble_runtime() {
    # handle persistence files
    move_persistence_files
}


# copy already built artifacts to the runtime image.
function runtime_assemble() {
    log_info "-----> [s2i-core] Running runtime assemble script"
    cd ${S2I_DESTINATION_DIR}/src
    if [ "${BINARY_BUILD^^}" == "TRUE" ] || ls | grep -E '*.jar|classes|maven*|*-runner|target|quarkus-app' 1> /dev/null 2>&1; then
        log_info "-----> Binary build enabled, artifacts were uploaded directly to the image build"
        if ls target 1> /dev/null 2>&1; then
            log_info "-----> Entire target dir uploaded."
            cd "target"    
        fi

        local result=$(file -b --mime-type *-runner | grep x-executable)
        if [ "$result" == "application/x-executable" ]; then
            log_info "-----> Found binary file, native build."
            NATIVE="TRUE"

        else
            if ls | grep -E '*-runner.jar' 1> /dev/null 2>&1;then
                log_info "-----> Found Quarkus runner.jar file, not native build."
                NATIVE="FALSE"

            elif ls | grep -E 'quarkus-app/*-run.jar' 1> /dev/null 2>&1;then
                log_info "-----> Found Quarkus app.jar file, not native build."
                NATIVE="FALSE"
            fi
        fi

        log_info "-----> Cleaning up unneeded jar files"
        rm -rfv *-tests.jar
        rm -rfv *-sources.jar

        log_info "-----> Copying uploaded files to "${KOGITO_HOME}""
        artifactDir="."
        ARTIFACT_DIR=$artifactDir
        copy_kogito_app
        copy_persistence_files
    else
        cp -Rv --parents ./* "${KOGITO_HOME}"/
    fi
    assemble_runtime
    log_info "-----> Cleaning up s2i directory"
    rm -rfv ${S2I_DESTINATION_DIR}/src/*
}

function build_kogito_app() {
    local RUNTIME_TYPE="${1:-$QUARKUS_RUNTIME_TYPE}"
    cd "${S2I_SOURCE_DIR}"

    nativeBuild=""
    if [ "${NATIVE^^}" == "TRUE" ]; then
        if [[ "${JBOSS_IMAGE_NAME}" =~ "rhpam-7" ]]; then
            log_warning "Container Image ${JBOSS_IMAGE_NAME} does not supports native builds, please refer to the documentation."
            exit 10
        else
            nativeBuild="-Dnative"
        fi
    fi

    if [ "${SCRIPT_DEBUG}" != "true" ]; then
        export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} --batch-mode"
    else 
        set -x
    fi

    if [ -f "pom.xml" ]; then
        log_info "---> Building application from source..."
        $MAVEN_HOME/bin/mvn clean package ${MAVEN_ARGS_APPEND} ${KOGITO_OPTS} ${nativeBuild} -s "${MAVEN_SETTINGS_PATH}" \
	    -DskipTests -Dmaven.test.skip -Dmaven.javadoc.skip=true -Dmaven.site.skip=true -Dmaven.source.skip=true \
	    -Djacoco.skip=true -Dcheckstyle.skip=true -Dfindbugs.skip=true -Dpmd.skip=true -Dfabric8.skip=true

    else
        log_info "---> Generating $RUNTIME_TYPE project structure for $PROJECT_ARTIFACT_ID..."
        local quarkus_platform_version
        if [ "${RUNTIME_TYPE}" == "${QUARKUS_RUNTIME_TYPE}" ]; then

            local quarkus_plugin="${QUARKUS_PLUGIN:-io.quarkus.platform:quarkus-maven-plugin}"
            if [[ "${JBOSS_IMAGE_NAME}" =~ "rhpam-7" ]]; then
                quarkus_plugin="${QUARKUS_PLUGIN:-com.redhat.quarkus.platform:quarkus-maven-plugin}"
            fi

            IFS=':' read -ra GAV <<< "${quarkus_plugin}"
            for i in "${GAV[@]}"; do
                if [[ "$i" =~ ^[0-9]{0,2}\.[0-9]{0,3} ]]; then
                    log_info "version [${i}] provided through QUARKUS_PLUGIN env."
                    quarkus_platform_version=${i}
                else
                    quarkus_platform_version=${QUARKUS_PLATFORM_VERSION} || exit 1
                fi
            done

            log_info "----> Using Quarkus ${quarkus_plugin}:${quarkus_platform_version} to bootstrap the application."

            $MAVEN_HOME/bin/mvn -B ${MAVEN_ARGS_APPEND} -s "${MAVEN_SETTINGS_PATH}" $(get_quarkus_platform_properties) \
                "${quarkus_plugin}":"${quarkus_platform_version}":create  \
                    -DprojectGroupId=$PROJECT_GROUP_ID \
                    -DprojectArtifactId=$PROJECT_ARTIFACT_ID \
                    -DprojectVersion=$PROJECT_VERSION \
                    -Dextensions="kogito,quarkus-smallrye-health,quarkus-smallrye-openapi,quarkus-resteasy,quarkus-resteasy-jackson"

            if [ ! -z ${QUARKUS_EXTRA_EXTENSIONS} ]; then
                log_info "----> Adding extra Quarkus extensions: ${QUARKUS_EXTRA_EXTENSIONS}"
                $MAVEN_HOME/bin/mvn ${MAVEN_ARGS_APPEND} -s "${MAVEN_SETTINGS_PATH}" $(get_quarkus_platform_properties) \
				-f $PROJECT_ARTIFACT_ID/pom.xml \
                                "${quarkus_plugin}":"${quarkus_platform_version}":add-extension \
                                -Dextensions="${QUARKUS_EXTRA_EXTENSIONS}"
            fi

            # Fix as we cannot rely on Quarkus platform
            # Should be removed once https://issues.redhat.com/browse/KOGITO-9120 is implemented
            if [ ! -z ${KOGITO_VERSION} ]; then
                echo "Replacing Kogito Platform BOM with version ${KOGITO_VERSION}"
                # [ ]* -> is a regexp pattern to match any number of spaces
                pattern_1="[ ]*<groupId>.*<\/groupId>"
                pattern_2="[ ]*<artifactId>quarkus-kogito-bom<\/artifactId>\n"
                pattern_3="[ ]*<version>.*<\/version>\n"
                complete_pattern="$pattern_1\n$pattern_2$pattern_3"

                replace_1="        <groupId>org.kie.kogito<\/groupId>\n"
                replace_2="        <artifactId>kogito-bom<\/artifactId>\n"
                replace_3="        <version>${KOGITO_VERSION}<\/version>\n"
                complete_replace="$replace_1$replace_2$replace_3"

                sed -i.bak -e "/$pattern_1/{
                    N;N;N
                    s/$complete_pattern/$complete_replace/
                    }" ${PROJECT_ARTIFACT_ID}/pom.xml
            fi

        elif [ "${RUNTIME_TYPE}" == "${SPRINGBOOT_RUNTIME_TYPE}" ]; then
            log_info "----> Using Spring Boot to bootstrap the application."
            $MAVEN_HOME/bin/mvn archetype:generate -B -DinteractiveMode=false -DarchetypeGroupId=org.kie.kogito \
                -DarchetypeArtifactId=kogito-spring-boot-archetype -DarchetypeVersion=$KOGITO_VERSION \
                -DgroupId=$PROJECT_GROUP_ID -DartifactId=$PROJECT_ARTIFACT_ID -Dversion=$PROJECT_VERSION \
                ${MAVEN_ARGS_APPEND} -s "${MAVEN_SETTINGS_PATH}"
        else
            log_error "---> Invalid RUNTIME_TYPE(${RUNTIME_TYPE}) provided, failing build..."
            exit 1
        fi

        # remove resources generated by the archetype
        log_info "--> Remove archetype generated resources"
        rm -rfv $PROJECT_ARTIFACT_ID/src/main/resources/*.{bpm,bpmn2,dmn,drl}

        local require_sw
        # copy resources into the generated project
        for item in *
        do
            if [ -d "${item}" ] && [ "${item}" == "$PROJECT_ARTIFACT_ID" ]; then
                log_info "--> Skipping generated project ..."
            else
                log_info "--> Copying resource ${item}"
                cp -Rv "${item}" $PROJECT_ARTIFACT_ID/src/main/resources

                if [[ ${item} =~ .*\.sw\.(yaml|yml|json) ]]; then
                    if [[ "${RUNTIME_TYPE}" == "${QUARKUS_RUNTIME_TYPE}" ]]; then
                        log_info "--> Found Serverless Workflow file. Will add Kogito Quarkus Workflows extension to the project."
                        require_sw="true"
                    else
                        log_warning "--> Builds from Serverless Workflow files are not supported for SpringBoot. Please build your project locally or use Quarkus."
                        break
                    fi
                fi
            fi
        done

        # move all project content into the current directory
        mv -v $PROJECT_ARTIFACT_ID/* .

        # add extension if needed
        if [ "${require_sw}" == "true" ]; then
            log_info "--> Adding Kogito Quarkus Workflows extension to the generated project."

            # we must set the evaluate version since forceStdout is not available in previous versions
            local quarkus_platform_version
            quarkus_platform_version=${QUARKUS_PLATFORM_VERSION} || exit 1
            log_info "--> Quarkus version is '$quarkus_platform_version'"

            $MAVEN_HOME/bin/mvn ${MAVEN_ARGS_APPEND} -s "${MAVEN_SETTINGS_PATH}" $(get_quarkus_platform_properties) \
                "${quarkus_plugin}":"${quarkus_platform_version}":add-extension \
                -Dextensions="org.kie.kogito:kogito-quarkus-serverless-workflow"
        fi

        $MAVEN_HOME/bin/mvn clean package ${MAVEN_ARGS_APPEND} ${KOGITO_OPTS} ${nativeBuild} -s "${MAVEN_SETTINGS_PATH}" \
            -DskipTests -Dmaven.test.skip -Dmaven.javadoc.skip=true -Dmaven.site.skip=true -Dmaven.source.skip=true \
            -Djacoco.skip=true -Dcheckstyle.skip=true -Dfindbugs.skip=true -Dpmd.skip=true -Dfabric8.skip=true
    fi

    log_info "---> Build finished, installing application from path $(pwd)"
}

function copy_kogito_app() {

    if [ "${NATIVE^^}" == "TRUE" ]; then
        if ls $artifactDir/*-runner 1> /dev/null 2>&1; then
            # quarkus native build binary
            log_info "---> Installing native application binaries"
            cp -v $artifactDir/*-runner "${KOGITO_HOME}"/bin/
            chmod +x "${KOGITO_HOME}"/bin/*-runner
        fi

    elif ls $artifactDir/*-runner.jar 1> /dev/null 2>&1; then
        # handle quarkus build files
        log_info "---> Installing runner jar file"
        cp -v $artifactDir/*-runner.jar "${KOGITO_HOME}"/bin
        if [ -d "${artifactDir}/lib" ]; then
            log_info "---> Copying application libraries"
            cp -r $artifactDir/lib/ "${KOGITO_HOME}"/bin
        fi

    elif ls $artifactDir/quarkus-app/*-run.jar 1> /dev/null 2>&1; then
        # handle quarkus 1.12+ build files
        log_info "---> Installing Quarkus 1.12+ Application files"
        # copy everything that resides on quarkus-app directory
        cp -rv $artifactDir/quarkus-app/* "${KOGITO_HOME}"/bin

    else
        # handle normal java builds
        log_info "---> Installing common application binaries"
        cp -v $artifactDir/*.jar "${KOGITO_HOME}"/bin
    fi
}

function get_runtime_type() {
    allowed_runtime_values=("$QUARKUS_RUNTIME_TYPE" "$SPRINGBOOT_RUNTIME_TYPE")
    local runtime_type="${QUARKUS_RUNTIME_TYPE}"

    jar_2_inspect="${KOGITO_HOME}/bin/*.jar"
    quarkus_main_class="io.quarkus.bootstrap.runner.QuarkusEntryPoint"
    spring_main_class="org.springframework.boot.loader.JarLauncher"
    if [ -f ${jar_2_inspect} ]; then
        log_info "---> Binary build, trying to detect runtime type based on the provided application jar."
        zipgrep "$quarkus_main_class" $jar_2_inspect > /dev/null
        if [ $? = 0 ]; then
            RUNTIME_TYPE="${QUARKUS_RUNTIME_TYPE}"
        else
            zipgrep "$spring_main_class" $jar_2_inspect > /dev/null
            if [ $? = 0 ]; then
                RUNTIME_TYPE="${SPRINGBOOT_RUNTIME_TYPE}"
            fi
        fi
    fi

    if [ "${RUNTIME_TYPE}x" = "x" ]; then
        RUNTIME_TYPE=${RUNTIME_TYPE:-${runtime_type}}
    fi

    if [[ ! "${allowed_runtime_values[*]}" =~ ${RUNTIME_TYPE} ]]; then
        log_warning "RUNTIME_TYPE ${RUNTIME_TYPE} is not allowed, the allowed types are [${allowed_runtime_values[*]}]. Application might fail"
    fi

    log_info "----> Setting RUNTIME_TYPE to ${RUNTIME_TYPE}"
    echo "${RUNTIME_TYPE}"
}

function get_quarkus_platform_properties() {
    local quarkus_platform_group_id="${QUARKUS_PLATFORM_GROUP_ID:-io.quarkus.platform}"
    local quarkus_platform_artifact_id="${QUARKUS_PLATFORM_ARTIFACT_ID:-quarkus-bom}"
    if [[ "${JBOSS_IMAGE_NAME}" =~ "rhpam-7" ]]; then
        quarkus_platform_group_id="${QUARKUS_PLATFORM_GROUP_ID:-com.redhat.quarkus.platform}"
        quarkus_platform_artifact_id="${QUARKUS_PLATFORM_ARTIFACT_ID:-quarkus-bom}"
    fi

    echo " -DplatformGroupId=${quarkus_platform_group_id} -DplatformArtifactId=${quarkus_platform_artifact_id} -DplatformVersion=${QUARKUS_PLATFORM_VERSION}"
}
